package com.yc.sole.system.biz;

import cn.hutool.core.bean.BeanUtil;
import com.yc.sole.common.constant.CacheConstant;
import com.yc.sole.common.enums.CacheType;
import com.yc.sole.framework.exception.BaseException;
import com.yc.sole.framework.mybatis.page.Paging;
import com.yc.sole.framework.mybatis.util.PageUtil;
import com.yc.sole.framework.result.BaseResultEnum;
import com.yc.sole.system.dto.CacheDto;
import com.yc.sole.system.exception.SysResultEnum;
import com.yc.sole.system.repository.CacheRepository;
import com.yc.sole.system.request.CacheQueryReq;
import com.yc.sole.system.request.CacheReq;
import com.yc.sole.system.response.CacheResp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * @author yizuomin
 * @date 2023/5/26 09:30
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class CacheBiz {

    private final RedissonClient redissonClient;
    private final CacheRepository cacheRepository;

    /**
     * 根据缓存编码获取缓存详情
     *
     * @param cacheId
     * @return
     */
    public List<CacheResp> getKeys(Long cacheId) {
        CacheDto cacheDto = cacheRepository.selectByCacheId(cacheId);
        if (Objects.isNull(cacheDto)) {
            throw new BaseException(SysResultEnum.CACHE_NOT_FOUND);
        }
        List<CacheResp> keysList = new ArrayList<>();
        if (CacheType.STRING.equals(cacheDto.getCacheType())) {
            String realityKey = CacheConstant.PREFIX + cacheDto.getCacheCode() + ":";
            Iterable<String> keysByPattern = redissonClient.getKeys().getKeysByPattern(realityKey + "*");
            for (String s : keysByPattern) {
                CacheResp cacheResp = new CacheResp();
                cacheResp.setCacheCode(s.replace(realityKey, ""));
                keysList.add(cacheResp);
            }
        } else {
            RMap<String, Object> map = redissonClient.getMap(CacheConstant.PREFIX + cacheDto.getCacheCode(), JsonJacksonCodec.INSTANCE);
            for (String key : map.keySet()) {
                CacheResp cacheResp = new CacheResp();
                cacheResp.setCacheCode(key);
                keysList.add(cacheResp);
            }
        }
        return keysList;
    }

    /**
     * 获取缓存详情
     *
     * @param cacheId
     * @param detailKey
     * @return
     */
    public Object getDetailByKey(Long cacheId, String detailKey) {
        CacheDto cacheDto = cacheRepository.selectByCacheId(cacheId);
        if (Objects.isNull(cacheDto)) {
            throw new BaseException(SysResultEnum.CACHE_NOT_FOUND);
        }
        if (CacheType.STRING.equals(cacheDto.getCacheType())) {
            String key = CacheConstant.PREFIX + cacheDto.getCacheCode() + ":" + detailKey;
            return redissonClient.getBucket(key, JsonJacksonCodec.INSTANCE).get();
        } else {
            String mapKey = CacheConstant.PREFIX + cacheDto.getCacheCode();
            return redissonClient.getMap(mapKey, JsonJacksonCodec.INSTANCE).get(detailKey);
        }

        /*RType type = redissonClient.getKeys().getType(key);
        Object result = null;
        if (RType.MAP.equals(type)) {
            // hash
            result = redissonClient.getMap(key).readAllMap();
        } else if (RType.SET.equals(type)) {
            // set
            result = redissonClient.getSet(key).readAll();
        } else if (RType.LIST.equals(type)) {
            // list
            result = redissonClient.getList(key).readAll();
        } else if (RType.ZSET.equals(type)) {
            // zset
            result = redissonClient.getSortedSet(key).readAll();
        } else if (RType.OBJECT.equals(type)) {
            result = redissonClient.getBucket(key, JsonJacksonCodec.INSTANCE).get();
        }
        return result;*/
    }

    /**
     * 根据key删除缓存
     *
     * @param cacheId
     * @param detailKey
     */
    public void deleteKey(Long cacheId, String detailKey) {
        CacheDto cacheDto = cacheRepository.selectByCacheId(cacheId);
        if (Objects.isNull(cacheDto)) {
            throw new BaseException(SysResultEnum.CACHE_NOT_FOUND);
        }
        if (CacheType.STRING.equals(cacheDto.getCacheType())) {
            String key = CacheConstant.PREFIX + cacheDto.getCacheCode() + ":" + detailKey;
            redissonClient.getBucket(key, JsonJacksonCodec.INSTANCE).delete();
        } else {
            String mapKey = CacheConstant.PREFIX + cacheDto.getCacheCode();
            redissonClient.getMap(mapKey, JsonJacksonCodec.INSTANCE).remove(detailKey);
        }
        /*String prefix = CacheConstant.PREFIX + cacheCode;
        String key = prefix + ":" + detailKey;
        RType type = redissonClient.getKeys().getType(key);
        if (RType.MAP.equals(type)) {
            // hash
            redissonClient.getMap(prefix).remove(detailKey);
        } else if (RType.SET.equals(type)) {
            // set
            redissonClient.getSet(prefix).remove(detailKey);
        } else if (RType.LIST.equals(type)) {
            // list
            redissonClient.getList(prefix).remove(detailKey);
        } else if (RType.ZSET.equals(type)) {
            // zset
            redissonClient.getSortedSet(prefix).remove(detailKey);
        } else if (RType.OBJECT.equals(type)) {
            redissonClient.getBucket(key, JsonJacksonCodec.INSTANCE).delete();
        }*/
    }

    /**
     * 新增
     *
     * @param cacheReq
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveCache(CacheReq cacheReq) {
        CacheDto dto = new CacheDto();
        BeanUtil.copyProperties(cacheReq, dto);
        cacheRepository.saveCache(dto);
    }

    /**
     * 修改
     *
     * @param cacheReq
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateCacheById(CacheReq cacheReq) {
        CacheDto dto = new CacheDto();
        BeanUtil.copyProperties(cacheReq, dto);
        cacheRepository.updateCacheById(dto);
    }

    /**
     * 删除
     *
     * @param ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteCache(Collection<Long> ids) {
        cacheRepository.deleteCacheByIds(ids);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param cacheQueryReq
     * @return
     */
    public Paging<CacheResp> selectCachePage(Paging<CacheQueryReq> page, CacheQueryReq cacheQueryReq) {
        Paging<CacheDto> paging = cacheRepository.selectCachePage(page, cacheQueryReq);
        return PageUtil.pageCopy(paging, CacheResp.class);
    }

    /**
     * 通过Id查询缓存配置
     *
     * @param cacheId
     * @return
     */
    public CacheResp selectCacheById(Long cacheId) {
        return BeanUtil.copyProperties(cacheRepository.selectByCacheId(cacheId), CacheResp.class);
    }
}
